﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

using Prism.Games.GalEngine.Scripts;
using Prism.Games.GalEngine.Scripts.Parser;

namespace Prism.Games.GalEngine.Scripts.Parser.GameRunner
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, IGameWindow
    {
        public MainWindow(ScriptParser parser, WindowConfig config)
        {
            InitializeComponent();
            this.WindowConfig = config;
            this.SetNativeSize(config.NativeHeight, config.NativeWidth);
            this.SetTitle(config.Name);
            this.Parser = parser;
            this.SizeToContent = System.Windows.SizeToContent.WidthAndHeight;
        }

        protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
        {
            if (this.CloseFromParser)
            {

            }
            else
            {
                if (this.IsClosing == false)
                {
                    e.Cancel = true;
                    Parser.End();

                    this.IsClosing = true;
                }
                else
                {
                    base.OnClosing(e);
                }
            }
        }

        public bool CloseFromParser { get; set; }

        private bool isClosing = false;
        public bool IsClosing { get { return this.isClosing; } set { this.isClosing = value; } }

        public void SaveWindowConfig()
        {
            if (!this.WindowConfig.IsFullScreen)
            {
                this.WindowConfig.WindowModeLeft = (int)this.Left;
                this.WindowConfig.WindowModeTop = (int)this.Top;
            }

            var file = GameFrameLibrary.Strings.WindowConfig;
            System.Xaml.XamlServices.Save(file, this.WindowConfig);
        }

        public void SetCursor(Uri source)
        {
            this.Cursor = new Cursor(source.LocalPath);
        }

        public ScriptParser Parser { get; set; }

        public WindowConfig WindowConfig { get; set; }

        public void SendWindowConfig(WindowConfig config)
        {
            this.WindowConfig = config;
        }

        public void SetContent(object content)
        {
            this.ContentControl.Content = content;
            this.ContentControl.Focus();
        }

        public void SetSecondContent(object content)
        {
            this.SecondContent.Content = content;
            this.SecondContent.Focus();
        }

        public void SetThirdContent(object content)
        {
            this.ThirdContent.Content = content;
            this.ThirdContent.Focus();
        }

        public void SetFourthContent(object content)
        {
            this.FourthContent.Content = content;
            this.FourthContent.Focus();
        }

        public object GetContent()
        {
            return this.ContentControl.Content;
        }

        public object GetSecondContent()
        {
            return this.SecondContent.Content;
        }

        public object GetMainContent()
        {
            return this.Content;
        }

        public object GetThirdContent()
        {
            return this.ThirdContent.Content;
        }

        public object GetFourthContent()
        {
            return this.FourthContent.Content;
        }

        public new object FindName(string name)
        {
            return (this.ContentControl.Content as FrameworkElement).FindName(name);
        }

        public object FindSecondName(string name)
        {
            return (this.SecondContent.Content as FrameworkElement).FindName(name);
        }

        public object FindMainName(string name)
        {
            return this.FindName(name);
        }

        public object FindThirdName(string name)
        {
            return (this.ThirdContent.Content as FrameworkElement).FindName(name);
        }

        public object FindFourthName(string name)
        {
            return (this.FourthContent.Content as FrameworkElement).FindName(name);
        }

        public new void Close()
        {
            base.Close();
        }

        public new void Show()
        {
            base.Show();
        }

        public new void Hide()
        {
            base.Hide();
        }

        public void SetNativeSize(int height, int width)
        {
            this.WindowConfig.NativeHeight = height;
            this.WindowConfig.NativeWidth = width;

            this.MainLayout.Height = height;
            this.MainLayout.Width = width;

        }

        public void Zoom(int height, int width)
        {
            var oldHeight = this.WindowConfig.NativeHeight;
            var oldWidth = this.WindowConfig.NativeWidth;

            var newHeight = height;
            var newWidth = width;

            double scaleY = (double)newHeight / (double)oldHeight;
            double scaleX = (double)newWidth / (double)oldWidth;

            this.XM.Height = height;
            this.XM.Width = width;

            #region 计算Block位置，判定分辨率，调整位置。
            if (newHeight * oldWidth == newWidth * oldHeight)
            {
                this.TopBlock.Height = 0; this.TopBlock.Width = 0;
                this.BottomBlock.Height = 0; this.BottomBlock.Width = 0;
                Canvas.SetTop(this.MainLayout, 0);
                Canvas.SetLeft(this.MainLayout, 0);

                // 注意，这里是一个关于屏幕长宽比的问题。
                this.MainLayout.LayoutTransform = new System.Windows.Media.ScaleTransform(scaleX, scaleY);
            }
            else
            {
                if (newHeight * oldWidth > newWidth * oldHeight)
                {
                    var b = oldHeight * scaleX;

                    var blockHeight = (newHeight - b) / 2;

                    Canvas.SetLeft(this.TopBlock, 0);
                    Canvas.SetTop(this.TopBlock, 0);
                    this.TopBlock.Width = newWidth;
                    this.TopBlock.Height = blockHeight;

                    Canvas.SetTop(this.MainLayout, blockHeight);
                    Canvas.SetLeft(this.MainLayout, 0);

                    Canvas.SetLeft(this.BottomBlock, 0);
                    Canvas.SetTop(this.BottomBlock, blockHeight + b);
                    this.BottomBlock.Width = newWidth;
                    this.BottomBlock.Height = blockHeight;

                    // 注意，这里是一个关于屏幕长宽比的问题。
                    this.MainLayout.LayoutTransform = new System.Windows.Media.ScaleTransform(scaleX, scaleX);
                }
                else
                {
                    var a = oldWidth * scaleY;

                    var blockWidth = (newWidth - a) / 2;

                    Canvas.SetTop(this.TopBlock, 0);
                    Canvas.SetLeft(this.TopBlock, 0);
                    this.TopBlock.Width = blockWidth;
                    this.TopBlock.Height = newHeight;

                    Canvas.SetTop(this.MainLayout, 0);
                    Canvas.SetLeft(this.MainLayout, blockWidth);

                    Canvas.SetTop(this.BottomBlock, 0);
                    Canvas.SetLeft(this.BottomBlock, blockWidth + a);
                    this.BottomBlock.Width = blockWidth;
                    this.BottomBlock.Height = newHeight;

                    // 注意，这里是一个关于屏幕长宽比的问题。
                    this.MainLayout.LayoutTransform = new System.Windows.Media.ScaleTransform(scaleY, scaleY);
                }
            }

            #endregion


            if (!this.WindowConfig.IsFullScreen)
            {
                // 将非全屏模式下的窗口大小记录
                this.WindowConfig.ZoomHeight = Convert.ToInt32(newHeight);
                this.WindowConfig.ZoomWidth = Convert.ToInt32(newWidth);
            }
        }

        public void Zoom(bool smallSize)
        {
            if (smallSize)
            {
                var h = Convert.ToInt32((double)this.WindowConfig.NativeHeight * (3d / 4d));
                var w = Convert.ToInt32((double)this.WindowConfig.NativeWidth * (3d / 4d));

                this.Zoom(h, w);
            }
            else
            {
                this.Zoom(this.WindowConfig.NativeHeight, this.WindowConfig.NativeWidth);
            }
        }

        public void FullScreen()
        {
            // 获取主屏幕的宽度和高度。
            var screenWidth = SystemParameters.PrimaryScreenWidth;
            var screenHeight = SystemParameters.PrimaryScreenHeight;

            // 设定窗口的位置。
            this.Left = 0;
            this.Top = 0;

            // 将窗口设置为无边框模式。
            this.WindowStyle = WindowStyle.None;

            this.Topmost = true;

            this.WindowConfig.IsFullScreen = true;

            // 将窗口缩放至全屏大小。
            this.Zoom(Convert.ToInt32(screenHeight), Convert.ToInt32(screenWidth));

        }

        public void ResumeWindowMode()
        {
            // 将窗口的位置恢复为非全屏模式下的窗口位置。
            this.Left = this.WindowConfig.WindowModeLeft;
            this.Top = this.WindowConfig.WindowModeTop;

            // 将窗口的边框复原。
            this.WindowStyle = System.Windows.WindowStyle.SingleBorderWindow;

            this.Topmost = false;

            // 将窗口缩放为非全屏模式下的窗口大小。
            this.Zoom(this.WindowConfig.ZoomHeight, this.WindowConfig.ZoomWidth);

            this.WindowConfig.IsFullScreen = false;
        }

        public void SetTitle(string title)
        {
            this.Title = title;
        }

        private void OnNextCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void OnNextExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            if (this.Parser.IsParsing)
            {
                return;
            }
            else this.Parser.StartCurrent();
        }

        private void OnNewGameCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void OnNewGameExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            if (this.Parser.IsParsing)
            {
                return;
            }
            else this.Parser.StartCurrent();
        }

        private void OnLoadGameCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void OnLoadGameExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            //Load
            this.Parser.EnterSaveDataLoaderGUI();
        }

        private void OnSaveGameCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void OnSaveGameExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            //Save
            this.Parser.EnterSaveDataSaverGUI();
        }

        private void OnConfigCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void OnConfigExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            this.Parser.EnterConfigGUI();
        }

        private void OnExitCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void OnExitExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            this.Parser.End();
        }

        private void OnTitleCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void OnTitleExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            this.Parser.Restart();
        }

        private void OnBackCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void OnBackExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            this.Parser.DeleteSecondContent();
        }

        private void OnLoadCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void OnLoadExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            if (e.Parameter != null)
            {
                this.Parser.LoadData(e.Parameter);
            }
        }

        private void OnSaveCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void OnSaveExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            this.Parser.SaveData(e.Parameter);
        }


        private void OnAutoCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void OnAutoExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            this.Parser.PlayHelper.SwitchAutoPlay();
        }

        private void OnMessageBannerOKCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void OnMessageBannerExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            this.Parser.MessageBannerOK(true);
        }

        private void OnMessageBannerCancelCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void OnMessageBannerCancelExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            this.Parser.MessageBannerOK(false);
        }

        private void OnOpenLogCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void OnOpenLogExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            this.Parser.LogManager.ShowLogFrame();
        }

        private void OnSkipCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void OnSkipExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            this.Parser.PlayHelper.SwitchSkipMode();
        }

        private void OnChangeAudioVolumeValueCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void OnChangeAudioVolumeValueExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            this.Parser.GameConfig.SetAudioVolume(e.Parameter as RoutedPropertyChangedEventArgs<double>);
        }

        private void OnFullScreenCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void OnFullScreenExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            this.Parser.GameConfig.SwitchFullScreen();
        }

        private void OnWindowCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void OnWindowExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            this.Parser.GameConfig.WindowMode();
        }

        private void OnSmallSizeCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void OnSmallSizeExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            this.Parser.GameConfig.SmallSize();
        }

        private void OnOriginalSizeCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void OnOriginalSizeExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            this.Parser.GameConfig.OriginalSize();
        }

        private void OnSkipNotReadCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void OnSkipNotReadExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            this.Parser.GameConfig.SwitchNotRead(true);
        }

        private void OnStopNotReadCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void OnStopNotReadExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            this.Parser.GameConfig.SwitchNotRead(false);
        }

        private void OnButtonMouseEnterCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void OnButtonMouseEnterExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            this.Parser.SystemSoundParser.PlaySystemSound(GameFrameLibrary.SystemSoundUris.MouseOver);
        }

        private void OnExecuteOptionCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void OnExecuteOptionExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            this.Parser.SelectorParser.ExecuteOption(e.Parameter as Prism.Games.GalEngine.Scripts.Data.BranchSystem.Option);
        }

        public System.Windows.Threading.Dispatcher GetDispatcher()
        {
            return this.Dispatcher;
        }

        private void OnHideMenuCanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void OnHideMenuExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            this.Parser.HideMenu();
        }
    }
}
